#include "DisplayPrimitive.h"


//Base class for anything that can be displayed
bool DisplayPrimitive::IsActive(){
	return mIsActive;
}

void DisplayPrimitive::SetIsActive( bool isActive ){
	mIsActive = isActive;
}

//SpriteDisplayPrimitive
void SpriteDisplayPrimitive::Display() {
	if (IsActive()){
		DrawSprite(&mSprite, mWorldPos, mWorldWH, mAngle);
	}
}

void SpriteDisplayPrimitive::SetPos(const glm::vec2 & inPos) {
	mWorldPos = inPos;
	mSprite.SetPos(inPos);
}

glm::vec2 SpriteDisplayPrimitive::GetPos() {
	return mSprite.GetPos();
}

Sprite * SpriteDisplayPrimitive::GetSprite() {
	return &mSprite;
}


//XXX Could this introduce drift?
void AnimatedSpriteDisplayPrimitive::NextFrame() {
	mCurrFrame.x += 1;
	
	glm::vec2 curruv = mSprite.GetUV();
	glm::vec2 curruvwh = mSprite.GetUVWH();
	glm::vec2 newuv;
	if (mCurrFrame.x >= mNumFrames.x) {
		mCurrFrame = glm::vec2(0, 0);
		newuv = glm::vec2( curruv.x - (curruvwh.x) * (mNumFrames.x-1), curruv.y - curruvwh.y * (mNumFrames.y-1) );
	}
	else {
		newuv = glm::vec2(curruv.x + curruvwh.x, curruv.y + curruvwh.y);
	}
	mSprite.SetUV( newuv );
}

void AnimatedSpriteDisplayPrimitive::PrevFrame() {
	mCurrFrame.x -= 1;
	
	glm::vec2 curruv = mSprite.GetUV();
	glm::vec2 curruvwh = mSprite.GetUVWH();
	glm::vec2 newuv;
	if (mCurrFrame.x <= 0) {
		mCurrFrame = glm::vec2( mNumFrames.x - 1, mNumFrames.y-1);
		newuv = glm::vec2( curruv.x + (curruvwh.x * mNumFrames.x-1), curruv.y + (curruvwh.y * mNumFrames.y-1) );
	}
	else {
		newuv = glm::vec2(curruv.x - curruvwh.x, curruv.y - curruvwh.y);
	}
	mSprite.SetUV( newuv );
}

void AnimatedSpriteDisplayPrimitive::SetSpriteSheetParams ( 
		int numFramesW,
		int numFramesH,
		int startFrameX, 
		int startFrameY
) 
	{
		mNumFrames = glm::ivec2(numFramesW, numFramesH);
		mCurrFrame = glm::ivec2(startFrameX, startFrameY);
		glm::vec2 uvwh( 1.0/(float)numFramesW, 1.0/(float)numFramesH );
		mSprite.SetUVWH( uvwh );
		mSprite.SetUV(glm::vec2( mCurrFrame.x * uvwh.x, mCurrFrame.y * uvwh.y ));
	}

void PhysicsDisplayPrimitive::Display() {
	DrawPhysicsPrimitive( mPrim );
}

void PhysicsDisplayPrimitive::SetPrimitive( PhysicsPrimitive * inPrim ){
	mPrim = inPrim;
}

PhysicsPrimitive * PhysicsDisplayPrimitive::GetPrimitive() {
	return mPrim;
}

DisplayPrimitive * CreateDisplayPrimitive( const DisplayPrimitiveDef * inDef )
{
	DisplayPrimitive * retVal = NULL;

	switch(inDef->type){
	case DISPLAY_PRIMITIVE:
		printf("Can't initialize a display primitive of an abstract base class DisplayPrimitive\n");
		break;
	case SPRITE_DISPLAY_PRIMITIVE:
		{
		SpriteDisplayPrimitiveDef * def = (SpriteDisplayPrimitiveDef *)(inDef);
		SpriteDisplayPrimitive * sp = 
			new SpriteDisplayPrimitive(static_cast<const SpriteDisplayPrimitiveDef*> (inDef) );
		retVal = sp;
		break;
		}
	case ANIMATED_SPRITE_DISPLAY_PRIMITIVE:
		{
		AnimatedSpriteDisplayPrimitiveDef * def = (AnimatedSpriteDisplayPrimitiveDef *)(inDef);
		AnimatedSpriteDisplayPrimitive * sp = 
			new AnimatedSpriteDisplayPrimitive(static_cast<const AnimatedSpriteDisplayPrimitiveDef *> (inDef));
		retVal = sp;
		break;
		}
	default:
		break;
	};

	return retVal;
}
